<?php

namespace Common\Controller;

use Think\View;

abstract class Addon extends BaseController
{
    protected $basePath = '';
    public $classname = '';
    public $addon_path;
    public $addon_relative_path;

    public function __construct()
    {
        $this->basePath = C('ADDON_PATH');
        $this->view = new View();
        $this->classname = self::get_class();
        // 计算包含地址
        $ex = explode('\\', $this->classname);
        $ex[0] = rtrim(C('AUTOLOAD_NAMESPACE.' . $ex[0]), '/\\');
        $this->addon_path = dirname(implode(DIRECTORY_SEPARATOR, $ex));
        // 计算相对地址
        $root = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $_SERVER['DOCUMENT_ROOT']);
        $this->addon_relative_path = str_replace(DIRECTORY_SEPARATOR, '/', str_replace($root, '', realpath($this->addon_path)));
        $this->addon_relative_path = '/'.ltrim($this->addon_relative_path, '/');
        if(method_exists($this,'_initialize')){
            $this->_initialize();
        }
        // 加载常规配置文件
//        $common_conf = $this->addon_path.'/Conf/config.php';
//        if(is_file($common_conf)) C(require $common_conf);
    }

    // 自动解析插件钩子  类似于别名
    public function __call($name, $arguments)
    {
        $hooklist = $this->register_hook();
        if ($hooklist[$name]) {
            if (is_array($hooklist[$name])) {
                // 队列模式
//                echo "队列模式";
                foreach ($hooklist[$name] as $k => $v) {
                    if ($v && method_exists($this, $v)) {
                        $this->{$v}($arguments);
                    }
                }
            } else if (is_string($hooklist[$name])) {
                // 别名模式
                if ($hooklist[$name] && method_exists($this, $hooklist[$name])) {
                    $this->{$hooklist[$name]}($arguments);
                }
            }
        } else if (array_search($name, $hooklist)) {
            // 原型模式
            if (method_exists($this, $name))
                $this->{$name}($arguments);
        } else {
            // 回到
            return parent::__call($name, $arguments);
        }
    }

    protected static function get_class()
    {
        return get_called_class();
    }

    // 重写渲染方法
    protected function display($templateFile = '', $charset = '', $contentType = '', $content = '', $prefix = '')
    {
        $templateFile = $this->getTmpl($templateFile);
        parent::display($templateFile, $charset, $contentType, $content, $prefix);
    }

    // 解析独立控制器的模版路径
    protected function getTmpl($template)
    {
        if (is_file($template))
            return $template;
        $module = preg_replace('!' . C('ADDON_BASE_EXT') . '$!', '', basename(str_replace('\\', DIRECTORY_SEPARATOR, get_class($this))));
        $file = $module . '/View/' . $template;
        $path = rtrim($this->basePath, '/') . '/' . $file . C('TMPL_TEMPLATE_SUFFIX');
        return $path;
    }

    /**
     * 注册钩子
     * 初步设想：
     * 返回钩子数组 用于告诉系统这个插件想要完成什么功能 要对哪些钩子进行实现
     * 数组结构：
     * ['系统钩子'=>'钩子的别名方法']
     * 或 ['系统钩子'=>['一些列的功能队列','一些列的功能队列','一些列的功能队列']] 这种写法多用于队列类型的功能
     * 或['系统钩子1','系统钩子2','系统钩子3',] 这种写法是最简便的，但执行的方法就只能是和系统钩子名称相同的本类的方法名了
     * 当然一个插件中允许你使用任意的钩子注册规则进行混合使用
     * @return array|void 必须返回
     */
    public function register_hook()
    {
    }

    /**
     * 新增配置
     * @param $name
     * @param $title
     * @param $value
     * @param string $filter
     * @param int $group
     * @return bool|mixed
     */
    public static function create_conf($name, $title, $value, $filter = 'serialize', $group = 1)
    {
        $model = D('Config');
        if (is_array($filter)) {
            $value = call_user_func($filter[0], $filter[1]);
        } else {
            if (function_exists($filter)) {
                $value = $filter($value);
            }
        }
        $data = $model->create(array(
            'type' => 'text',
            'group' => $group,
            'name' => $name,
            'title' => $title,
            'value' => $value,
        ));
        $data = $model->create($data);
        if ($data) {
            return $model->add($data);
        }
        return false;
    }

    /**
     * 保存配置
     * @param $name
     * @param $value
     * @param string $filter
     * @return bool
     */
    public static function save_conf($name, $value, $filter = 'serialize')
    {
        $map = array('name' => $name);
        if (is_array($filter)) {
            $value = call_user_func($filter[0], $filter[1]);
        } else {
            if (function_exists($filter)) {
                $value = $filter($value);
            }
        }
        $data = array(
            'value' => $value,
        );
        $res = D('Config')->where($map)->save($data);
        return $res !== false ? true : false;
    }

    /**
     * 获取配置
     * @param $name
     * @param string $filter
     * @return mixed
     */
    public static function get_conf($name, $filter = 'unserialize')
    {
        $v = C($name);
        if (is_array($filter)) {
            $v = call_user_func($filter[0], $filter[1]);
        } else {
            if (function_exists($filter)) {
                $v = $filter($v);
            }
        }
        return $v;
    }

    public function create_menu($data, $pid = 0, $code = false)
    {
        $model = D('UserRule');
        foreach ($data as &$row) {
            $row['pid'] = $pid;
            if ($code) $row['code'] = $code;
            $d = $model->create($row);
            if (!$d) continue;
            $id = $model->add($d);
            if ($row['_child']) {
                $this->create_menu($row['_child'], $id, $code);
            }
        }
    }

    public function delete_menu($map)
    {
        $model = D('UserRule');
        return $model->where($map)->delete();
    }
}